home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume3 / hold2 < prev    next >
Encoding:
Text File  |  1989-02-03  |  5.4 KB  |  221 lines

  1. Path: xanth!mcnc!rutgers!ucsd!ames!necntc!ncoast!allbery
  2. From: bill@qst1.tcc.com (Bill Cox)
  3. Newsgroups: comp.sources.misc
  4. Subject: v03i077: hold -- terminate a pipe with its input
  5. Message-ID: <8807050034.AA23702@ccicpg>
  6. Date: 3 Jul 88 21:04:10 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: bill@qst1.tcc.com (Bill Cox)
  9. Lines: 209
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. Posting-number: Volume 3, Issue 77
  13. Submitted-by: "Bill Cox" <bill@qst1.tcc.com>
  14. Archive-name: hold2
  15.  
  16. [Is my memory going?  I don't remember seeing a first version of this.  ++bsa]
  17.  
  18. Here's an unpdated version of hold.c, that lets you terminate a pipe with its
  19. input file, effectively putting the output back into the input file, as in
  20.     tail SYSLOG | hold SYSLOG
  21. This version contains some fixes noticed by readers at ncoast.
  22.  
  23. To build it, simply
  24.     cc -O -o hold hold.c
  25. It's been compiled and run under V7, SYSV, XENIX and MS-DOS in its present 
  26. form.
  27.  
  28. Questions/bugs/flames to Bill Cox, (714)631-4452 (voice)
  29.             or uunet!ccicpg!qst1!bill
  30.  
  31. RATIONALE: Why use hold?
  32.  
  33. Let's say you have the file tmp, which contains:
  34. AA#AAAA
  35. BBBB#BB
  36.  
  37. And you wish to change the '#'s to '~'s. If you
  38. simply say sed 's/#/~/' tmp, you see
  39. AA~AAAA
  40. BBBB~BB
  41. just as you would expect.
  42.  
  43. Now, enter sed 's/#/~/' tmp > tmp (in effect asking the shell to
  44. over-write the input file with the output) then cat tmp.  Surprise,
  45. tmp is a null file!
  46.  
  47. Now, enter sed 's/#/~/' tmp | hold tmp; cat tmp
  48. AA~AAAA
  49. BBBB~BB
  50. Just as you expect.  Because hold creates a temporary file FOR YOU,
  51. which doesn't appear as an output on the command line.
  52.  
  53. #! /bin/sh
  54. # This is a shell archive.  Remove anything before this line, then unpack
  55. # it by saving it into a file and typing "sh file".  To overwrite existing
  56. # files, type "sh file -c".  You can also feed this as standard input via
  57. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  58. # will see the following message at the end:
  59. #        "End of shell archive."
  60. # Contents:  hold.c
  61. # Wrapped by srcs@qst1 on Mon Jul  4 17:21:31 1988
  62. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  63. if test -f 'hold.c' -a "${1}" != "-c" ; then 
  64.   echo shar: Will not clobber existing file \"'hold.c'\"
  65. else
  66. echo shar: Extracting \"'hold.c'\" \(2960 characters\)
  67. sed "s/^X//" >'hold.c' <<'END_OF_FILE'
  68. X/*
  69. X * hold  terminate a pipe, gather stdin into a temporary,
  70. X *     then rename the temporary to the argument's name.
  71. X *
  72. X * Example: ... | hold filename
  73. X *    or: ... | hold > filename
  74. X *
  75. X */
  76. X
  77. X#ifdef MSDOS
  78. X#include <io.h>
  79. X#endif
  80. X
  81. X#include <stdio.h>
  82. X#include <errno.h>
  83. X#ifndef    MSDOS
  84. X#include <signal.h>
  85. X#endif
  86. XFILE *fp = NULL;
  87. Xint stdoutf;
  88. X
  89. X#ifdef MSDOS
  90. Xchar fname[11] = "holdXXXXXX";
  91. X#endif
  92. X#ifdef M_XENIX
  93. Xchar fname[11] = "holdXXXXXX";
  94. X#else
  95. Xchar fname[20] = "/usr/tmp/holdXXXXXX";
  96. X#endif
  97. X
  98. X
  99. Xextern int errno;    /* Declare global error value. */
  100. X
  101. X#ifndef MSDOS
  102. X/* This routine gains control when a signal is trapped.  It unlinks the
  103. X * temporary file.  This is necessary when a pipe gets broken.
  104. X */
  105. Xint    Trap()
  106. X{
  107. Xunlink(fname);    /* Ignore errors at this point, we are dead anyway. */
  108. Xexit(1);
  109. X}
  110. X#endif
  111. X
  112. Xint main(argc, argv)
  113. X    int argc;
  114. X    char *argv[];
  115. X{
  116. X    int c;
  117. X
  118. X    stdoutf = 0;
  119. X    if (argc > 1)
  120. X        stdoutf = 1;
  121. X        
  122. X    if (argc > 2) {
  123. X    fprintf(stderr, "Usage: ... | hold filename\n");
  124. X    fprintf(stderr, " or    ... | hold > filename\n");
  125. X    return(1);
  126. X    }
  127. X#ifndef MSDOS
  128. X    /* Trap signals to remove file on. */
  129. X    signal(SIGHUP, Trap);
  130. X    signal(SIGINT, Trap);
  131. X    signal(SIGQUIT, Trap);
  132. X    signal(SIGTERM, Trap);
  133. X#endif
  134. X    if ((fp = fopen(mktemp(fname), "w")) == NULL) 
  135. X    errclean(2, "open %s", fname, 0);
  136. X    
  137. X    while ((c = getchar()) != EOF)
  138. X    fputc(c, fp);
  139. X
  140. X    if (ferror(stdin) || ferror(fp))
  141. X         errclean(3, "copy stdin to %s", 0, fname);
  142. X        
  143. X    if (fclose(fp) != 0) 
  144. X    errclean(4, "close %s", fname, 0);
  145. X
  146. X    if (stdoutf) {
  147. X        if (rename(fname, argv[1]) != 0)    
  148. X            errclean(5, "rename %s to %s", fname, argv[1]);
  149. X    }
  150. X    else {
  151. X    if ((fp = fopen(fname, "r")) == NULL) 
  152. X        errclean(6, "open %s", fname, 0);
  153. X    
  154. X    while ((c = getc(fp)) != EOF)
  155. X        fputc(c, stdout);
  156. X
  157. X    if (ferror(stdout) || ferror(fp))
  158. X            errclean(7, "copy %s to stdout", 0, fname);
  159. X        
  160. X    if (fclose(fp) != 0) 
  161. X        errclean(8, "close %s", fname, 0);
  162. X
  163. X    if (unlink(fname) != 0)
  164. X        errclean(9, "remove %s", fname, 0);
  165. X    }
  166. X
  167. X    return(0);
  168. X}
  169. X
  170. X
  171. X#ifndef MSDOS
  172. Xint rename(s1, s2)        /* s2 = new name, s1 = existing name */
  173. X    char *s1, *s2;
  174. X{
  175. X    /* assure that new name doesn't exist */
  176. X    if (unlink(s2) != 0 && errno != ENOENT) {
  177. X    errclean(10, "remove %s", s2, 0);
  178. X        return(1);   
  179. X        }
  180. X    /* connect new name to existing file */
  181. X    if (link(s1, s2) != 0) {
  182. X    errclean(11, "link %s to %s", s1, s2);
  183. X        return(1);   
  184. X        }
  185. X    /* remove old name for the file */
  186. X    if (unlink(s1) != 0) {
  187. X    errclean(12, "remove %s", s1, 0);
  188. X        return(1);   
  189. X        }
  190. X    return(0);
  191. X}
  192. X#endif
  193. X
  194. X/*
  195. X * errclean - output error message and exit to system
  196. X */
  197. Xerrclean(code, string, arg1, arg2)
  198. X    int code;
  199. X    char *string;
  200. X    char *arg1, *arg2;
  201. X{
  202. X    char lstr[80];
  203. X
  204. X    if (fp != NULL) {
  205. X    (void)unlink(fname);
  206. X        fp = NULL;
  207. X    }
  208. X    sprintf(lstr, "hold %2d: can't %s\n", code, string);
  209. X    fprintf(stderr, lstr, arg1, arg2);
  210. X    exit(code);
  211. X}
  212. X
  213. END_OF_FILE
  214. if test 2960 -ne `wc -c <'hold.c'`; then
  215.     echo shar: \"'hold.c'\" unpacked with wrong size!
  216. fi
  217. # end of 'hold.c'
  218. fi
  219. echo shar: End of shell archive.
  220. exit 0
  221.